package xyz.xxin.xat.slsurface;

import android.opengl.GLSurfaceView;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

public class MyRenderer implements GLSurfaceView.Renderer {
    float[] triangleData = new float[] {
            0.0f, -0.5f, 0.0f,
            -0.3f, 0.0f, 0.0f,
            0.3f, 0.1f, 0.0f
    };
    int[] triangleColor = new int[] {
            65535, 0, 0, 0,
            0, 65535, 0, 0,
            0, 0, 65535, 0
    };

    FloatBuffer triangleDataBuffer;
    IntBuffer triangleColorBuffer;

    public MyRenderer() {
        triangleDataBuffer = floatBufferUtil(triangleData);
        triangleColorBuffer = intBufferUtil(triangleColor);
    }

    private IntBuffer intBufferUtil(int[] ints) {
        IntBuffer intBuffer;
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(ints.length * 4);
        byteBuffer.order(ByteOrder.nativeOrder());
        intBuffer = byteBuffer.asIntBuffer();
        intBuffer.put(ints);
        intBuffer.position(0);
        return intBuffer;
    }

    private FloatBuffer floatBufferUtil(float[] floats) {
        FloatBuffer floatBuffer;
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(floats.length * 4);
        byteBuffer.order(ByteOrder.nativeOrder());
        floatBuffer = byteBuffer.asFloatBuffer();
        floatBuffer.put(floats);
        floatBuffer.position(0);
        return floatBuffer;
    }

    @Override
    public void onSurfaceCreated(GL10 gl10, EGLConfig eglConfig) {
        // 创建 GLSurfaceView 时调用一次此方法

        // 关闭抗抖动，提高性能（该方法用于禁用OpenGL ES某方面的特性）
        gl10.glDisable(GL10.GL_DITHER);
        // 设置系统对透视进行修正（该方法用于对OpenGL ES某方面进行修正）
        gl10.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST);
        // 用于设置OpenGL ES清屏所使用的颜色，四个参数分别对应红、绿、蓝、透明度，最小值0最大值1
        gl10.glClearColor(1,1,1,0);
        // 设置阴影平滑模式（用于设置OpenGL ES的阴影模式）
        gl10.glShadeModel(GL10.GL_SMOOTH);
        // 启用深度测试（与glDisable相对，用于启用OpenGL ES某方面的特性）
        gl10.glEnable(GL10.GL_DEPTH_TEST);
        // 设置深度测试类型
        gl10.glDepthFunc(GL10.GL_LEQUAL);
    }

    @Override
    public void onSurfaceChanged(GL10 gl10, int width, int height) {
        // GLSurfaceView 几何图形发生变化（包括 GLSurfaceView 大小发生变化或设备屏幕方向发生变化）时调用此方法

        // 设置3D视窗的大小及位置，前两个参数指定位置，后两个参数指定宽高
        gl10.glViewport(0,0, width, height);
        // 将当前矩阵模式设置为投影矩阵，通常接收GL10.GL_PROJECTION和GL10.GL_MODELVIEW两个值
        gl10.glMatrixMode(GL10.GL_PROJECTION);
        // 初始化单位矩阵，将坐标系的原点移到了屏幕中心，类似于一个复位操作
        gl10.glLoadIdentity();
        // 计算透视视窗的宽度、高度比
        float ratio = (float) width / height;
        // 设置透视视窗的空间大小
        // 前两个参数设置X轴上的最小、最大坐标值，中间两个参数设置Y轴的最小、最大值，后两个参数设置Z轴上的最小、最大值
        gl10.glFrustumf(-ratio, ratio, -1, 1, 1, 10);
    }

    @Override
    public void onDrawFrame(GL10 gl10) {
        // 每次重新绘制 GLSurfaceView 时调用此方法

        // 清除屏幕缓存和深度缓存
        gl10.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
        // 启用顶点坐标数据
        gl10.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        // 启用顶点颜色数据
        gl10.glEnableClientState(GL10.GL_COLOR_ARRAY);
        // 设置当前矩阵堆栈为模型堆栈
        gl10.glMatrixMode(GL10.GL_MODELVIEW);

        // 三角形
        gl10.glLoadIdentity();
        // 沿着 X, Y 和 Z 轴移动
        gl10.glTranslatef(0.0f, 0.0f, -2.0f);
        // 设置顶点的位置数据
        gl10.glVertexPointer(3, GL10.GL_FLOAT, 0, triangleDataBuffer);
        // 设置顶点的颜色数据
        gl10.glColorPointer(4, GL10.GL_FIXED, 0, triangleColorBuffer);
        // 根据顶点数据绘制平面图形
        gl10.glDrawArrays(GL10.GL_TRIANGLES, 0, 3);

        // 绘制结束
        gl10.glFinish();
        gl10.glDisableClientState(GL10.GL_VERTEX_ARRAY);
    }
}
